import * as underscore from './utils/underscore';

// 函数 柯里化 闭包
// 第一版
// var curry = function (func) {
//   var args = [].slice.call(arguments, 1);
//   return function () {
//     var newArgs = args.concat([].slice.call(arguments));
//     return func.apply(this, newArgs);
//   }
// }


// function add (a, b) {
//   return a + b;
// }

// var addCurry = curry(add);

// console.log(addCurry(4, 5))

// 第二版
// function sub_curry (fn) {
//   var args = [].slice.call(arguments, 1);
//   return function () {
//     return fn.apply(this, args.concat([].slice.call(arguments)));
//   };
// }

// function curry (fn, length) {
//   length = length || fn.length;

//   var slice = Array.prototype.slice;

//   return function () {
//     if (arguments.length < length) {
//       var combined = [fn].concat(slice.call(arguments));
//       return curry(sub_curry.apply(this, combined), length - arguments.length);
//     } else {
//       return fn.apply(this, arguments);
//     }
//   }
// }

// var fn = curry((a, b, c) => [a, b, c]);

// console.log(fn('a', 'b', 'c'));
// console.log(fn('a', 'b')('c'));
// console.log(fn('a')('b')('c'));

// 更易懂的实现
// function curry (fn, args) {
//   var length = fn.length;
//   args = args || [];
//   return function () {
//     var _args = args.slice(0);
//     var arg = null;
//     var i = 0;
//     for (; i < arguments.length; i++) {
//       arg = arguments[i];
//       _args.push(arg);
//     }
//     if (_args.length < length) {
//       return curry.call(this, fn, _args);
//     } else {
//       return fn.apply(this, _args);
//     }
//   }
// }

// var fn = curry((a, b, c) => {
//   console.log([a, b, c]);
// });

// fn('a', 'b', 'c')
// fn('a', 'b')('b')
// fn('a')('b')('c')

// 柯里化理解：用闭包把参数保存起来，当参数的数量足够执行函数了，就开始执行函数。

// 高颜值写法
var curry = fn => judge = (...args) => args.length === fn.length ? fn(...args) : (...arg) => judge(...args, ...arg)

var judge = curry((a, b, c, d) => {
  console.log([a, b, c, d]);
})

judge('a', 'b')('c')('d')

// 第三版
// function curry(fn, args, holes) {
//   length = fn.length;

//   args = args || [];

//   holes = holes || [];

//   return function() {

//       var _args = args.slice(0),
//           _holes = holes.slice(0),
//           argsLen = args.length,
//           holesLen = holes.length,
//           arg, i, index = 0;

//       for (i = 0; i < arguments.length; i++) {
//           arg = arguments[i];
//           // 处理类似 fn(1, _, _, 4)(_, 3) 这种情况，index 需要指向 holes 正确的下标
//           if (arg === _ && holesLen) {
//               index++
//               if (index > holesLen) {
//                   _args.push(arg);
//                   _holes.push(argsLen - 1 + index - holesLen)
//               }
//           }
//           // 处理类似 fn(1)(_) 这种情况
//           else if (arg === _) {
//               _args.push(arg);
//               _holes.push(argsLen + i);
//           }
//           // 处理类似 fn(_, 2)(1) 这种情况
//           else if (holesLen) {
//               // fn(_, 2)(_, 3)
//               if (index >= holesLen) {
//                   _args.push(arg);
//               }
//               // fn(_, 2)(1) 用参数 1 替换占位符
//               else {
//                   _args.splice(_holes[index], 1, arg);
//                   _holes.splice(index, 1)
//               }
//           }
//           else {
//               _args.push(arg);
//           }

//       }
//       if (_holes.length || _args.length < length) {
//           return curry.call(this, fn, _args, _holes);
//       }
//       else {
//           return fn.apply(this, _args);
//       }
//   }
// }

// var _ = {};

// var fn = curry(function(a, b, c, d, e) {
//   console.log([a, b, c, d, e]);
// });

// // 验证 输出全部都是 [1, 2, 3, 4, 5]
// fn(1, 2, 3, 4, 5);
// fn(1,2, _, _, _)(4, 3)(5);
